void StructuredBuffer::ReadFromFile(const wchar* path, ID3D11Device* device) { // Open the file HANDLE fileHandle = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if(fileHandle == INVALID_HANDLE_VALUE) Win32Call(false); // Read the buffer info bool32 dynamic, useAsUAV, hiddenCounter, appendConsume; DWORD bytesRead = 0; Win32Call(ReadFile(fileHandle, &Size, 4, &bytesRead, nullptr)); Win32Call(ReadFile(fileHandle, &Stride, 4, &bytesRead, nullptr)); Win32Call(ReadFile(fileHandle, &NumElements, 4, &bytesRead, nullptr)); Win32Call(ReadFile(fileHandle, &dynamic, 4, &bytesRead, nullptr)); Win32Call(ReadFile(fileHandle, &useAsUAV, 4, &bytesRead, nullptr)); Win32Call(ReadFile(fileHandle, &hiddenCounter, 4, &bytesRead, nullptr)); Win32Call(ReadFile(fileHandle, &appendConsume, 4, &bytesRead, nullptr)); // Read the buffer data UINT8* bufferData = new UINT8[Size]; Win32Call(ReadFile(fileHandle, bufferData, Size, &bytesRead, nullptr)); // Close the file Win32Call(CloseHandle(fileHandle)); // Init Initialize(device, Stride, NumElements, dynamic, useAsUAV, appendConsume, hiddenCounter, bufferData); // Clean up delete [] bufferData; }
Timer::Timer() { // Query for the performance counter frequency LARGE_INTEGER largeInt; Win32Call(QueryPerformanceFrequency(&largeInt)); frequency = largeInt.QuadPart; frequencyD = static_cast<double>(frequency); // Init the elapsed time Win32Call(QueryPerformanceCounter(&largeInt)); startTime = largeInt.QuadPart; elapsed = largeInt.QuadPart - startTime; elapsedF = static_cast<float>(elapsed); elapsedSeconds = elapsed / frequency; elapsedSecondsD = elapsed / frequencyD; elapsedSecondsF = static_cast<float>(elapsedSecondsD); elapsedMilliseconds = static_cast<int64>(elapsedSecondsD * 1000); elapsedMillisecondsD = elapsedSecondsD * 1000; elapsedMillisecondsF = static_cast<float>(elapsedMillisecondsD); elapsedMicroseconds = static_cast<int64>(elapsedMillisecondsD * 1000); elapsedMicrosecondsD = elapsedMillisecondsD * 1000; elapsedMicrosecondsF = static_cast<float>(elapsedMillisecondsD); delta = 0; deltaF = 0; deltaMilliseconds = 0; deltaMillisecondsF = 0; deltaMicroseconds = 0; deltaMicrosecondsF = 0; }
void File::Open(const wchar* filePath, OpenMode openMode_) { Assert_(fileHandle == INVALID_HANDLE_VALUE); openMode = openMode_; if(openMode == OpenRead) { Assert_(FileExists(filePath)); // Open the file fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(fileHandle == INVALID_HANDLE_VALUE) Win32Call(false); } else { // If the exists, delete it if(FileExists(filePath)) Win32Call(DeleteFile(filePath)); // Create the file fileHandle = CreateFile(filePath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if(fileHandle == INVALID_HANDLE_VALUE) Win32Call(false); } }
Timer::Timer() { // Set the thread affinity of the calling thread so that it stays on the // same logical processor. QPC can give bogus results if you don't do this. HANDLE threadHandle = GetCurrentThread(); Win32Call(SetThreadAffinityMask(threadHandle, 1) != 0); // Query for the performance counter frequency LARGE_INTEGER largeInt; Win32Call(QueryPerformanceFrequency(&largeInt)); frequency = largeInt.QuadPart; frequencyD = static_cast<double>(frequency); // Init the elapsed time Win32Call(QueryPerformanceCounter(&largeInt)); elapsed = largeInt.QuadPart; elapsedF = static_cast<float>(elapsed); elapsedSeconds = elapsed / frequency; elapsedSecondsD = elapsed / frequencyD; elapsedSecondsF = static_cast<float>(elapsedSecondsD); elapsedMilliseconds = static_cast<INT64>(elapsedSecondsD * 1000); elapsedMillisecondsD = elapsedSecondsD * 1000; elapsedMillisecondsF = static_cast<float>(elapsedMillisecondsD); elapsedMicroseconds = static_cast<INT64>(elapsedMillisecondsD * 1000); elapsedMicrosecondsD = elapsedMillisecondsD * 1000; elapsedMicrosecondsF = static_cast<float>(elapsedMillisecondsD); delta = 0; deltaF = 0; deltaMilliseconds = 0; deltaMillisecondsF = 0; deltaMicroseconds = 0; deltaMicrosecondsF = 0; }
void Timer::Update() { LARGE_INTEGER largeInt; Win32Call(QueryPerformanceCounter(&largeInt)); int64 currentTime = largeInt.QuadPart - startTime; delta = currentTime - elapsed; deltaF = static_cast<float>(deltaF); deltaSeconds = delta / frequency; deltaSecondsD = delta / frequencyD; deltaSecondsF = static_cast<float>(deltaSecondsD); deltaMillisecondsD = deltaSecondsD * 1000; deltaMilliseconds = static_cast<int64>(deltaMillisecondsD); deltaMillisecondsF = static_cast<float>(deltaMillisecondsD); deltaMicrosecondsD = deltaMillisecondsD * 1000; deltaMicroseconds = static_cast<int64>(deltaMicrosecondsD); deltaMicrosecondsF = static_cast<float>(deltaMicrosecondsD); elapsed = currentTime; elapsedF = static_cast<float>(elapsed); elapsedSeconds = elapsed / frequency; elapsedSecondsD = elapsed / frequencyD; elapsedSecondsF = static_cast<float>(elapsedSecondsD); elapsedMilliseconds = static_cast<int64>(elapsedSecondsD * 1000); elapsedMillisecondsD = elapsedSecondsD * 1000; elapsedMillisecondsF = static_cast<float>(elapsedMillisecondsD); elapsedMicroseconds = static_cast<int64>(elapsedMillisecondsD * 1000); elapsedMicrosecondsD = elapsedMillisecondsD * 1000; elapsedMicrosecondsF = static_cast<float>(elapsedMillisecondsD); }
void File::Write(uint64 size, const void* data) const { Assert_(fileHandle != INVALID_HANDLE_VALUE); Assert_(openMode == OpenWrite); DWORD bytesWritten = 0; Win32Call(WriteFile(fileHandle, data, static_cast<DWORD>(size), &bytesWritten, NULL)); }
void File::Read(uint64 size, void* data) const { Assert_(fileHandle != INVALID_HANDLE_VALUE); Assert_(openMode == OpenRead); DWORD bytesRead = 0; Win32Call(ReadFile(fileHandle, data, static_cast<DWORD>(size), &bytesRead, NULL)); }
// Gets the last written timestamp of the file uint64 GetFileTimestamp(const wchar* filePath) { Assert_(filePath); WIN32_FILE_ATTRIBUTE_DATA attributes; Win32Call(GetFileAttributesEx(filePath, GetFileExInfoStandard, &attributes)); return attributes.ftLastWriteTime.dwLowDateTime | (uint64(attributes.ftLastWriteTime.dwHighDateTime) << 32); }
uint64 File::Size() const { Assert_(fileHandle != INVALID_HANDLE_VALUE); LARGE_INTEGER fileSize; Win32Call(GetFileSizeEx(fileHandle, &fileSize)); return fileSize.QuadPart; }
void File::Close() { if(fileHandle == INVALID_HANDLE_VALUE) return; // Close the file Win32Call(CloseHandle(fileHandle)); fileHandle = INVALID_HANDLE_VALUE; }
void StructuredBuffer::WriteToFile(const wchar* path, ID3D11Device* device, ID3D11DeviceContext* context) { Assert_(Buffer != nullptr); // Get the buffer info D3D11_BUFFER_DESC desc; Buffer->GetDesc(&desc); uint32 useAsUAV = (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) ? 1 : 0; uint32 dynamic = (desc.BindFlags & D3D11_USAGE_DYNAMIC) ? 1 : 0; uint32 appendConsume = 0; uint32 hiddenCounter = 0; if(useAsUAV) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; UAView->GetDesc(&uavDesc); appendConsume = (uavDesc.Format & D3D11_BUFFER_UAV_FLAG_APPEND) ? 1 : 0; hiddenCounter =(uavDesc.Format & D3D11_BUFFER_UAV_FLAG_COUNTER) ? 1 : 0; } // If the exists, delete it if(FileExists(path)) Win32Call(DeleteFile(path)); // Create the file HANDLE fileHandle = CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr); if(fileHandle == INVALID_HANDLE_VALUE) Win32Call(false); // Write the buffer info DWORD bytesWritten = 0; Win32Call(WriteFile(fileHandle, &Size, 4, &bytesWritten, nullptr)); Win32Call(WriteFile(fileHandle, &Stride, 4, &bytesWritten, nullptr)); Win32Call(WriteFile(fileHandle, &NumElements, 4, &bytesWritten, nullptr)); Win32Call(WriteFile(fileHandle, &dynamic, 4, &bytesWritten, nullptr)); Win32Call(WriteFile(fileHandle, &useAsUAV, 4, &bytesWritten, nullptr)); Win32Call(WriteFile(fileHandle, &hiddenCounter, 4, &bytesWritten, nullptr)); Win32Call(WriteFile(fileHandle, &appendConsume, 4, &bytesWritten, nullptr)); // Get the buffer data StagingBuffer stagingBuffer; stagingBuffer.Initialize(device, Size); context->CopyResource(stagingBuffer.Buffer, Buffer); const void* bufferData= stagingBuffer.Map(context); // Write the data to the file Win32Call(WriteFile(fileHandle, bufferData, Size, &bytesWritten, nullptr)); // Un-map the staging buffer stagingBuffer.Unmap(context); // Close the file Win32Call(CloseHandle(fileHandle)); }
static ID3DBlob* CompileShader(const wchar* path, const char* functionName, const char* profile, const D3D_SHADER_MACRO* defines, bool forceOptimization, vector<wstring>& filePaths) { // Make a hash off the expanded shader code string shaderCode = GetExpandedShaderCode(path, filePaths); wstring cacheName = MakeShaderCacheName(shaderCode, functionName, profile, defines); if(FileExists(cacheName.c_str())) { File cacheFile(cacheName.c_str(), File::OpenRead); const uint64 shaderSize = cacheFile.Size(); vector<uint8> compressedShader; compressedShader.resize(shaderSize); cacheFile.Read(shaderSize, compressedShader.data()); ID3DBlob* decompressedShader[1] = { nullptr }; uint32 indices[1] = { 0 }; DXCall(D3DDecompressShaders(compressedShader.data(), shaderSize, 1, 0, indices, 0, decompressedShader, nullptr)); return decompressedShader[0]; } std::printf("Compiling shader %s %s %s\n", WStringToAnsi(GetFileName(path).c_str()).c_str(), profile, MakeDefinesString(defines).c_str()); // Loop until we succeed, or an exception is thrown while(true) { UINT flags = D3DCOMPILE_WARNINGS_ARE_ERRORS; #ifdef _DEBUG flags |= D3DCOMPILE_DEBUG; if(forceOptimization == false) flags |= D3DCOMPILE_SKIP_OPTIMIZATION; #endif ID3DBlob* compiledShader; ID3DBlobPtr errorMessages; HRESULT hr = D3DCompileFromFile(path, defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, functionName, profile, flags, 0, &compiledShader, &errorMessages); if(FAILED(hr)) { if(errorMessages) { wchar message[1024] = { 0 }; char* blobdata = reinterpret_cast<char*>(errorMessages->GetBufferPointer()); MultiByteToWideChar(CP_ACP, 0, blobdata, static_cast<int>(errorMessages->GetBufferSize()), message, 1024); std::wstring fullMessage = L"Error compiling shader file \""; fullMessage += path; fullMessage += L"\" - "; fullMessage += message; // Pop up a message box allowing user to retry compilation int retVal = MessageBoxW(nullptr, fullMessage.c_str(), L"Shader Compilation Error", MB_RETRYCANCEL); if(retVal != IDRETRY) throw DXException(hr, fullMessage.c_str()); #if EnableShaderCaching_ shaderCode = GetExpandedShaderCode(path); cacheName = MakeShaderCacheName(shaderCode, functionName, profile, defines); #endif } else { _ASSERT(false); throw DXException(hr); } } else { // Compress the shader D3D_SHADER_DATA shaderData; shaderData.pBytecode = compiledShader->GetBufferPointer(); shaderData.BytecodeLength = compiledShader->GetBufferSize(); ID3DBlobPtr compressedShader; DXCall(D3DCompressShaders(1, &shaderData, D3D_COMPRESS_SHADER_KEEP_ALL_PARTS, &compressedShader)); // Create the cache directory if it doesn't exist if(DirectoryExists(baseCacheDir.c_str()) == false) Win32Call(CreateDirectory(baseCacheDir.c_str(), nullptr)); if(DirectoryExists(cacheDir.c_str()) == false) Win32Call(CreateDirectory(cacheDir.c_str(), nullptr)); File cacheFile(cacheName.c_str(), File::OpenWrite); // Write the compiled shader to disk uint64 shaderSize = compressedShader->GetBufferSize(); cacheFile.Write(shaderSize, compressedShader->GetBufferPointer()); return compiledShader; } } }
int32 App::Run() { try { if(createConsole) { Win32Call(AllocConsole()); Win32Call(SetConsoleTitle(applicationName.c_str())); FILE* consoleFile = nullptr; freopen_s(&consoleFile, "CONOUT$", "wb", stdout); } window.SetClientArea(deviceManager.BackBufferWidth(), deviceManager.BackBufferHeight()); deviceManager.Initialize(window); if(showWindow) window.ShowWindow(); blendStates.Initialize(deviceManager.Device()); rasterizerStates.Initialize(deviceManager.Device()); depthStencilStates.Initialize(deviceManager.Device()); samplerStates.Initialize(deviceManager.Device()); // Create a font + SpriteRenderer font.Initialize(L"Arial", 18, SpriteFont::Regular, true, deviceManager.Device()); spriteRenderer.Initialize(deviceManager.Device()); Profiler::GlobalProfiler.Initialize(deviceManager.Device(), deviceManager.ImmediateContext()); window.RegisterMessageCallback(WM_SIZE, OnWindowResized, this); // Initialize AntTweakBar TwCall(TwInit(TW_DIRECT3D11, deviceManager.Device())); // Create a tweak bar tweakBar = TwNewBar("Settings"); std::string helpTextDefinition = MakeAnsiString(" GLOBAL help='%s' ", globalHelpText.c_str()); TwCall(TwDefine(helpTextDefinition.c_str())); TwCall(TwDefine(" GLOBAL fontsize=3 ")); Settings.Initialize(tweakBar); TwHelper::SetValuesWidth(Settings.TweakBar(), 120, false); AppSettings::Initialize(deviceManager.Device()); Initialize(); AfterReset(); while(window.IsAlive()) { if(!window.IsMinimized()) { timer.Update(); Settings.Update(); CalculateFPS(); AppSettings::Update(); Update(timer); UpdateShaders(deviceManager.Device()); AppSettings::UpdateCBuffer(deviceManager.ImmediateContext()); Render(timer); // Render the profiler text spriteRenderer.Begin(deviceManager.ImmediateContext(), SpriteRenderer::Point); Profiler::GlobalProfiler.EndFrame(spriteRenderer, font); spriteRenderer.End(); { PIXEvent pixEvent(L"Ant Tweak Bar"); // Render the TweakBar UI TwCall(TwDraw()); } deviceManager.Present(); } window.MessageLoop(); } } catch(SampleFramework11::Exception exception) { exception.ShowErrorMessage(); return -1; } ShutdownShaders(); TwCall(TwTerminate()); if(createConsole) { fclose(stdout); FreeConsole(); } return returnCode; }
static ID3DBlob* CompileShader(const wchar* path, const char* functionName, ShaderType type, ShaderProfile profile, const D3D_SHADER_MACRO* defines, bool forceOptimization, GrowableList<wstring>& filePaths) { if(FileExists(path) == false) { Assert_(false); throw Exception(L"Shader file " + std::wstring(path) + L" does not exist"); } uint64 profileIdx = uint64(profile) * uint64(ShaderType::NumTypes) + uint64(type); Assert_(profileIdx < TotalNumProfiles); const char* profileString = ProfileStrings[profileIdx]; // Make a hash off the expanded shader code string shaderCode = GetExpandedShaderCode(path, filePaths); wstring cacheName = MakeShaderCacheName(shaderCode, functionName, profileString, defines); if(FileExists(cacheName.c_str())) { File cacheFile(cacheName.c_str(), FileOpenMode::Read); const uint64 shaderSize = cacheFile.Size(); Array<uint8> compressedShader; compressedShader.Init(shaderSize); cacheFile.Read(shaderSize, compressedShader.Data()); ID3DBlob* decompressedShader[1] = { nullptr }; uint32 indices[1] = { 0 }; DXCall(D3DDecompressShaders(compressedShader.Data(), shaderSize, 1, 0, indices, 0, decompressedShader, nullptr)); return decompressedShader[0]; } WriteLog("Compiling %s shader %s_%s %s\n", TypeStrings[uint64(type)], WStringToAnsi(GetFileName(path).c_str()).c_str(), functionName, MakeDefinesString(defines).c_str()); // Loop until we succeed, or an exception is thrown while(true) { UINT flags = D3DCOMPILE_WARNINGS_ARE_ERRORS; #ifdef _DEBUG flags |= D3DCOMPILE_DEBUG; // This is causing some shader bugs /*if(forceOptimization == false) flags |= D3DCOMPILE_SKIP_OPTIMIZATION;*/ #endif ID3DBlob* compiledShader; ID3DBlobPtr errorMessages; FrameworkInclude include; HRESULT hr = D3DCompileFromFile(path, defines, &include, functionName, profileString, flags, 0, &compiledShader, &errorMessages); if(FAILED(hr)) { if(errorMessages) { wchar message[1024] = { 0 }; char* blobdata = reinterpret_cast<char*>(errorMessages->GetBufferPointer()); MultiByteToWideChar(CP_ACP, 0, blobdata, static_cast<int>(errorMessages->GetBufferSize()), message, 1024); std::wstring fullMessage = L"Error compiling shader file \""; fullMessage += path; fullMessage += L"\" - "; fullMessage += message; // Pop up a message box allowing user to retry compilation int retVal = MessageBoxW(nullptr, fullMessage.c_str(), L"Shader Compilation Error", MB_RETRYCANCEL); if(retVal != IDRETRY) throw DXException(hr, fullMessage.c_str()); } else { Assert_(false); throw DXException(hr); } } else { // Compress the shader D3D_SHADER_DATA shaderData; shaderData.pBytecode = compiledShader->GetBufferPointer(); shaderData.BytecodeLength = compiledShader->GetBufferSize(); ID3DBlobPtr compressedShader; DXCall(D3DCompressShaders(1, &shaderData, D3D_COMPRESS_SHADER_KEEP_ALL_PARTS, &compressedShader)); // Create the cache directory if it doesn't exist if(DirectoryExists(baseCacheDir.c_str()) == false) Win32Call(CreateDirectory(baseCacheDir.c_str(), nullptr)); if(DirectoryExists(cacheDir.c_str()) == false) Win32Call(CreateDirectory(cacheDir.c_str(), nullptr)); File cacheFile(cacheName.c_str(), FileOpenMode::Write); // Write the compiled shader to disk uint64 shaderSize = compressedShader->GetBufferSize(); cacheFile.Write(shaderSize, compressedShader->GetBufferPointer()); return compiledShader; } } }