- fix incorrect use of block vs. sector aligned (both offset and length must be block-aligned to allow proper caching)
- use helper functions to reduce occurrences of BLOCK_SIZE and SECTOR_SIZE - wmi: provide for shutting it down (gets rid of its two threads); only initialize if actually needed (costs 200ms) - ogl_tex: don't complain if there's no gfx_card info (due to not having used wmi) This was SVN commit r5572.
This commit is contained in:
parent
aebf8cbf68
commit
58360a629c
@ -26,6 +26,7 @@
|
||||
#include "lib/file/file.h"
|
||||
#include "lib/file/file_system_posix.h"
|
||||
#include "lib/file/io/io.h"
|
||||
#include "lib/file/io/io_align.h" // BLOCK_SIZE
|
||||
#include "lib/file/io/write_buffer.h"
|
||||
|
||||
static FileSystem_Posix s_fileSystemPosix;
|
||||
@ -243,7 +244,7 @@ public:
|
||||
return 'A';
|
||||
}
|
||||
|
||||
virtual LibError Load(const std::string& UNUSED(name), shared_ptr<u8> buf, size_t size) const
|
||||
virtual LibError Load(const std::string& name, shared_ptr<u8> buf, size_t size) const
|
||||
{
|
||||
AdjustOffset();
|
||||
|
||||
@ -456,7 +457,7 @@ private:
|
||||
static LibError LocateCentralDirectory(PIFile file, off_t fileSize, off_t& cd_ofs, uint& cd_numEntries, off_t& cd_size)
|
||||
{
|
||||
const off_t maxScanSize = 66000u; // see below
|
||||
shared_ptr<u8> buf = io_Allocate(maxScanSize, ~0); // assume worst-case for alignment
|
||||
shared_ptr<u8> buf = io_Allocate(maxScanSize, BLOCK_SIZE-1); // assume worst-case for alignment
|
||||
|
||||
// expected case: ECDR at EOF; no file comment
|
||||
LibError ret = ScanForEcdr(file, fileSize, const_cast<u8*>(buf.get()), sizeof(ECDR), cd_numEntries, cd_ofs, cd_size);
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "lib/lockfree.h"
|
||||
#include "lib/allocators/pool.h"
|
||||
#include "lib/fnv_hash.h"
|
||||
#include "io_internal.h"
|
||||
#include "io_align.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -12,12 +12,13 @@
|
||||
#include "io.h"
|
||||
|
||||
#include "lib/allocators/allocators.h" // AllocatorChecker
|
||||
#include "lib/bits.h" // IsAligned, round_up
|
||||
#include "lib/sysdep/cpu.h" // cpu_memcpy
|
||||
#include "lib/file/file.h"
|
||||
#include "lib/file/common/file_stats.h"
|
||||
#include "block_cache.h"
|
||||
#include "io_internal.h"
|
||||
#include "io_align.h"
|
||||
|
||||
static const unsigned ioDepth = 8;
|
||||
|
||||
|
||||
// the underlying aio implementation likes buffer and offset to be
|
||||
@ -93,9 +94,7 @@ shared_ptr<u8> io_Allocate(size_t size, off_t ofs)
|
||||
{
|
||||
debug_assert(size != 0);
|
||||
|
||||
const size_t misalignment = ofs % SECTOR_SIZE;
|
||||
const size_t paddedSize = (size_t)round_up(size+misalignment, BLOCK_SIZE);
|
||||
|
||||
const size_t paddedSize = PaddedSize((off_t)size, ofs);
|
||||
u8* mem = (u8*)page_aligned_alloc(paddedSize);
|
||||
if(!mem)
|
||||
throw std::bad_alloc();
|
||||
@ -119,7 +118,7 @@ public:
|
||||
{
|
||||
m_file = file;
|
||||
m_blockId = BlockId(file->Pathname(), alignedOfs);
|
||||
if(false && file->Mode() == 'r' && s_blockCache.Retrieve(m_blockId, m_cachedBlock))
|
||||
if(file->Mode() == 'r' && s_blockCache.Retrieve(m_blockId, m_cachedBlock))
|
||||
{
|
||||
stats_block_cache(CR_HIT);
|
||||
|
||||
@ -206,9 +205,9 @@ public:
|
||||
: m_ofs(ofs), m_alignedBuf(alignedBuf), m_size(size)
|
||||
, m_totalIssued(0), m_totalTransferred(0)
|
||||
{
|
||||
m_misalignment = ofs % SECTOR_SIZE;
|
||||
m_alignedOfs = ofs - (off_t)m_misalignment;
|
||||
m_alignedSize = round_up(m_misalignment+size, BLOCK_SIZE);
|
||||
m_alignedOfs = AlignedOffset(ofs);
|
||||
m_alignedSize = PaddedSize(size, ofs);
|
||||
m_misalignment = ofs - m_alignedOfs;
|
||||
}
|
||||
|
||||
LibError Run(PIFile file, IoCallback cb = 0, uintptr_t cbData = 0)
|
||||
@ -241,9 +240,9 @@ public:
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
size_t Misalignment() const
|
||||
off_t AlignedOfs() const
|
||||
{
|
||||
return m_misalignment;
|
||||
return m_alignedOfs;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -302,15 +301,15 @@ LibError io_Read(PIFile file, off_t ofs, u8* alignedBuf, size_t size, u8*& data)
|
||||
{
|
||||
IoSplitter splitter(ofs, alignedBuf, (off_t)size);
|
||||
RETURN_ERR(splitter.Run(file));
|
||||
data = alignedBuf + splitter.Misalignment();
|
||||
data = alignedBuf + ofs - splitter.AlignedOfs();
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
LibError io_WriteAligned(PIFile file, off_t alignedOfs, const u8* alignedData, size_t size)
|
||||
{
|
||||
debug_assert(IsAligned(alignedOfs, SECTOR_SIZE));
|
||||
debug_assert(IsAligned(alignedData, SECTOR_SIZE));
|
||||
debug_assert(IsAligned_Offset(alignedOfs));
|
||||
debug_assert(IsAligned_Data(alignedData));
|
||||
|
||||
IoSplitter splitter(alignedOfs, const_cast<u8*>(alignedData), (off_t)size);
|
||||
return splitter.Run(file);
|
||||
@ -319,8 +318,8 @@ LibError io_WriteAligned(PIFile file, off_t alignedOfs, const u8* alignedData, s
|
||||
|
||||
LibError io_ReadAligned(PIFile file, off_t alignedOfs, u8* alignedBuf, size_t size)
|
||||
{
|
||||
debug_assert(IsAligned(alignedOfs, SECTOR_SIZE));
|
||||
debug_assert(IsAligned(alignedBuf, SECTOR_SIZE));
|
||||
debug_assert(IsAligned_Offset(alignedOfs));
|
||||
debug_assert(IsAligned_Data(alignedBuf));
|
||||
|
||||
IoSplitter splitter(alignedOfs, alignedBuf, (off_t)size);
|
||||
return splitter.Run(file);
|
||||
|
23
source/lib/file/io/io_align.cpp
Normal file
23
source/lib/file/io/io_align.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "precompiled.h"
|
||||
#include "io_align.h"
|
||||
|
||||
|
||||
bool IsAligned_Offset(off_t ofs)
|
||||
{
|
||||
return IsAligned(ofs, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
off_t AlignedOffset(off_t ofs)
|
||||
{
|
||||
return round_down(ofs, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
off_t AlignedSize(off_t size)
|
||||
{
|
||||
return round_up(size, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
off_t PaddedSize(off_t size, off_t ofs)
|
||||
{
|
||||
return round_up(size + ofs - AlignedOffset(ofs), BLOCK_SIZE);
|
||||
}
|
35
source/lib/file/io/io_align.h
Normal file
35
source/lib/file/io/io_align.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef INCLUDED_IO_ALIGN
|
||||
#define INCLUDED_IO_ALIGN
|
||||
|
||||
#include "lib/bits.h" // IsAligned, round_up
|
||||
|
||||
/**
|
||||
* block := power-of-two sized chunk of a file.
|
||||
* all transfers are expanded to naturally aligned, whole blocks.
|
||||
* (this makes caching parts of files feasible; it is also much faster
|
||||
* for some aio implementations, e.g. wposix.)
|
||||
* (blocks are also thereby page-aligned, which allows write-protecting
|
||||
* file buffers without worrying about their boundaries.)
|
||||
**/
|
||||
static const size_t BLOCK_SIZE = 256*KiB;
|
||||
|
||||
// note: *sizes* and *offsets* are aligned to blocks to allow zero-copy block cache.
|
||||
// that the *buffer* need only be sector-aligned (we assume 4kb for simplicity)
|
||||
// (this is a requirement of the underlying Windows OS)
|
||||
static const size_t SECTOR_SIZE = 4*KiB;
|
||||
|
||||
|
||||
template<class T>
|
||||
bool IsAligned_Data(T* address)
|
||||
{
|
||||
return IsAligned((uintptr_t)address, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
extern bool IsAligned_Offset(off_t ofs);
|
||||
|
||||
|
||||
extern off_t AlignedOffset(off_t ofs);
|
||||
extern off_t AlignedSize(off_t size);
|
||||
extern off_t PaddedSize(off_t size, off_t ofs);
|
||||
|
||||
#endif // #ifndef INCLUDED_IO_ALIGN
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* block := power-of-two sized chunk of a file.
|
||||
* all transfers are expanded to naturally aligned, whole blocks.
|
||||
* (this makes caching parts of files feasible; it is also much faster
|
||||
* for some aio implementations, e.g. wposix.)
|
||||
* (blocks are also thereby page-aligned, which allows write-protecting
|
||||
* file buffers without worrying about their boundaries.)
|
||||
**/
|
||||
static const size_t BLOCK_SIZE = 256*KiB;
|
||||
|
||||
// note: *sizes* are aligned to blocks to allow zero-copy block cache.
|
||||
// that the *buffer* and *offset* must be sector aligned (we assume 4kb for simplicity)
|
||||
// is a requirement of the OS.
|
||||
static const size_t SECTOR_SIZE = 4*KiB;
|
||||
|
||||
static const unsigned ioDepth = 8;
|
@ -4,7 +4,7 @@
|
||||
#include "lib/bits.h" // IsAligned
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "io.h"
|
||||
#include "io_internal.h"
|
||||
#include "io_align.h"
|
||||
|
||||
|
||||
WriteBuffer::WriteBuffer()
|
||||
@ -40,8 +40,8 @@ void WriteBuffer::Overwrite(const void* data, size_t size, size_t offset)
|
||||
UnalignedWriter::UnalignedWriter(PIFile file, off_t ofs)
|
||||
: m_file(file), m_alignedBuf(io_Allocate(BLOCK_SIZE))
|
||||
{
|
||||
const size_t misalignment = (size_t)ofs % SECTOR_SIZE;
|
||||
m_alignedOfs = ofs - (off_t)misalignment;
|
||||
m_alignedOfs = AlignedOffset(ofs);
|
||||
const size_t misalignment = (size_t)(ofs - m_alignedOfs);
|
||||
if(misalignment)
|
||||
io_ReadAligned(m_file, m_alignedOfs, m_alignedBuf.get(), BLOCK_SIZE);
|
||||
m_bytesUsed = misalignment;
|
||||
|
@ -12,13 +12,13 @@
|
||||
#include "file_cache.h"
|
||||
|
||||
#include "lib/file/common/file_stats.h"
|
||||
#include "lib/file/io/io_internal.h" // sectorSize
|
||||
#include "lib/cache_adt.h" // Cache
|
||||
#include "lib/bits.h" // round_up
|
||||
#include "lib/file/io/io_align.h" // BLOCK_SIZE
|
||||
#include "lib/cache_adt.h" // Cache
|
||||
#include "lib/bits.h" // round_up
|
||||
#include "lib/allocators/allocators.h"
|
||||
#include "lib/allocators/shared_ptr.h"
|
||||
#include "lib/allocators/headerless.h"
|
||||
#include "lib/allocators/mem_util.h" // mem_PageSize
|
||||
#include "lib/allocators/mem_util.h" // mem_PageSize
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -647,8 +647,8 @@ void ogl_tex_override(OglTexOverrides what, OglTexAllow allow)
|
||||
// called once from the first ogl_tex_upload.
|
||||
static void detect_gl_upload_caps()
|
||||
{
|
||||
// make sure us and the app hook have graphics card info available
|
||||
debug_assert(gfx_card[0] != '\0'); // gfx_detect must be called before ogl_tex_upload
|
||||
// note: gfx_card will be empty if running in quickstart mode;
|
||||
// in that case, we won't be able to check for known faulty cards.
|
||||
|
||||
// detect features, but only change the variables if they were at
|
||||
// "undecided" (if overrides were set before this, they must remain).
|
||||
|
@ -13,13 +13,10 @@
|
||||
|
||||
#include <wbemidl.h>
|
||||
|
||||
#include "winit.h"
|
||||
#include "lib/module_init.h"
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
WINIT_REGISTER_EARLY_INIT(wmi_Init);
|
||||
WINIT_REGISTER_EARLY_SHUTDOWN(wmi_Shutdown);
|
||||
|
||||
|
||||
static IWbemServices* pSvc;
|
||||
|
||||
@ -27,9 +24,13 @@ _COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator));
|
||||
_COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
|
||||
_COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject));
|
||||
|
||||
static ModuleInitState initState;
|
||||
|
||||
static LibError wmi_Init()
|
||||
static LibError Init()
|
||||
{
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return INFO::SKIPPED;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
@ -59,24 +60,26 @@ static LibError wmi_Init()
|
||||
}
|
||||
|
||||
|
||||
static LibError wmi_Shutdown()
|
||||
void wmi_Shutdown()
|
||||
{
|
||||
// the memory pointed to by pSvc is already invalidated at this point;
|
||||
// maybe some other module has already wiped out COM?
|
||||
//pSvc->Release();
|
||||
if(!ModuleShouldShutdown(&initState))
|
||||
return;
|
||||
|
||||
pSvc->Release();
|
||||
|
||||
// note: don't shut down COM because other modules may still be using it.
|
||||
//CoUninitialize();
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
LibError wmi_GetClass(const char* className, WmiMap& wmiMap)
|
||||
{
|
||||
HRESULT hr;
|
||||
Init();
|
||||
|
||||
IEnumWbemClassObjectPtr pEnum = 0;
|
||||
char query[200];
|
||||
sprintf_s(query, ARRAY_SIZE(query), "SELECT * FROM %s", className);
|
||||
hr = pSvc->ExecQuery(L"WQL", _bstr_t(query), WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, 0, &pEnum);
|
||||
HRESULT hr = pSvc->ExecQuery(L"WQL", _bstr_t(query), WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, 0, &pEnum);
|
||||
if(FAILED(hr))
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
debug_assert(pEnum);
|
||||
|
@ -26,4 +26,6 @@ typedef std::map<std::wstring, VARIANT> WmiMap;
|
||||
**/
|
||||
extern LibError wmi_GetClass(const char* className, WmiMap& wmiMap);
|
||||
|
||||
extern void wmi_Shutdown();
|
||||
|
||||
#endif // #ifndef INCLUDED_WMI
|
||||
|
@ -278,7 +278,7 @@ public:
|
||||
if(isWrite)
|
||||
ok = WriteFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
|
||||
else
|
||||
ok = ReadFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
|
||||
ok = ReadFile(hFile, buf, u64_lo(size), &bytesTransferred, &m_overlapped);
|
||||
if(!ok && GetLastError() == ERROR_IO_PENDING) // "pending" isn't an error
|
||||
{
|
||||
ok = TRUE;
|
||||
|
@ -978,8 +978,10 @@ void Init(const CmdLineArgs& args, uint flags)
|
||||
uint quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file
|
||||
SetTextureQuality(quality);
|
||||
|
||||
// required by ogl_tex to detect broken gfx card/driver combos
|
||||
gfx_detect();
|
||||
// needed by ogl_tex to detect broken gfx card/driver combos,
|
||||
// but takes a while due to WMI startup, so make it optional.
|
||||
if(!g_Quickstart)
|
||||
gfx_detect();
|
||||
|
||||
ogl_WarnIfError();
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "lib/sysdep/snd.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "lib/tex/tex.h"
|
||||
#include "lib/file/io/io_internal.h" // BLOCK_SIZE
|
||||
#include "lib/file/io/io_align.h" // BLOCK_SIZE
|
||||
|
||||
#include "ps/GameSetup/Config.h"
|
||||
#include "ps/GameSetup/GameSetup.h"
|
||||
|
Loading…
Reference in New Issue
Block a user