static void ClearFinishedUploads(uint64 flushCount) { const uint64 start = UploadSubmissionStart; const uint64 used = UploadSubmissionUsed; for(uint64 i = 0; i < used; ++i) { const uint64 idx = (start + i) % MaxUploadSubmissions; UploadSubmission& submission = UploadSubmissions[idx]; Assert_(submission.Size > 0); Assert_(submission.FenceValue != uint64(-1)); Assert_(UploadBufferUsed >= submission.Size); if(i < flushCount) UploadFence.Wait(submission.FenceValue); if(UploadFence.Signaled(submission.FenceValue)) { UploadSubmissionStart = (UploadSubmissionStart + 1) % MaxUploadSubmissions; UploadSubmissionUsed -= 1; UploadBufferStart = (UploadBufferStart + submission.Padding) % UploadBufferSize; Assert_(submission.Offset == UploadBufferStart); Assert_(UploadBufferStart + submission.Size <= UploadBufferSize); UploadBufferStart = (UploadBufferStart + submission.Size) % UploadBufferSize; UploadBufferUsed -= (submission.Size + submission.Padding); submission.Reset(); if(UploadBufferUsed == 0) UploadBufferStart = 0; } } }
void GetBoundCornersFromPoints(const XMFLOAT3* points, uint32 numPoints, uint32 stride, XMVECTOR &minx, XMVECTOR &maxx, XMVECTOR &miny, XMVECTOR &maxy, XMVECTOR &minz, XMVECTOR &maxz) { Assert_(numPoints > 0); Assert_(points); minx = maxx = miny = maxy = minz = maxz = XMLoadFloat3(points); for (uint32 i = 1; i < numPoints; i++) { XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride)); float px = XMVectorGetX(Point); float py = XMVectorGetY(Point); float pz = XMVectorGetZ(Point); if (px < XMVectorGetX(minx)) minx = Point; if (px > XMVectorGetX(maxx)) maxx = Point; if (py < XMVectorGetY(miny)) miny = Point; if (py > XMVectorGetY(maxy)) maxy = Point; if (pz < XMVectorGetZ(minz)) minz = Point; if (pz > XMVectorGetZ(maxz)) maxz = Point; } }
float AverageSpectrumSamples(const float *lambda, const float *vals, int n, float lambdaStart, float lambdaEnd) { for (int i = 0; i < n - 1; ++i) Assert_(lambda[i + 1] > lambda[i]); Assert_(lambdaStart < lambdaEnd); // Handle cases with out-of-bounds range or single sample only if (lambdaEnd <= lambda[0]) return vals[0]; if (lambdaStart >= lambda[n - 1]) return vals[n - 1]; if (n == 1) return vals[0]; float sum = 0; // Add contributions of constant segments before/after samples if (lambdaStart < lambda[0]) sum += vals[0] * (lambda[0] - lambdaStart); if (lambdaEnd > lambda[n - 1]) sum += vals[n - 1] * (lambdaEnd - lambda[n - 1]); // Advance to first relevant wavelength segment int i = 0; while (lambdaStart > lambda[i + 1]) ++i; Assert_(i + 1 < n); // Loop over wavelength sample segments and add contributions auto interp = [lambda, vals](float w, int i) { return SpectrumLerp((w - lambda[i]) / (lambda[i + 1] - lambda[i]), vals[i], vals[i + 1]); }; for (; i + 1 < n && lambdaEnd >= lambda[i]; ++i) { float segLambdaStart = std::max(lambdaStart, lambda[i]); float segLambdaEnd = std::min(lambdaEnd, lambda[i + 1]); sum += 0.5f * (interp(segLambdaStart, i) + interp(segLambdaEnd, i)) * (segLambdaEnd - segLambdaStart); } return sum / (lambdaEnd - lambdaStart); }
SceneObject *Scene::addDynamicOpaqueBoxObject(float scale, const Float3 &pos, const Quaternion &rot) { Assert_(_numObjectBases < MAX_DYNAMIC_OBJECTS); Assert_(_numTotalModelsShared < MAX_MODELS); Assert_(_numObjectBases < MAX_OBJECT_MATRICES); Assert_(_numPrevWVPs < MAX_OBJECT_MATRICES); if (!_boxModel) { addBoxModel(); _modelIndices.push_back(_numTotalModelsShared - 1); } uint64 modelIndex = getModelIndex(_boxModel); Assert_(modelIndex != -1); _objectBases[_numObjectBases] = createBase(scale, pos, rot); _prevWVPs[_numPrevWVPs] = _objectBases[_numObjectBases]; _sceneStaticOpaqueObjectBounds[_numStaticOpaqueObjects] = SceneObjectBound(); SceneObject &obj = _dynamicOpaqueObjects[_numDynamicOpaqueObjects]; obj.base = &_objectBases[_numObjectBases]; obj.model = _boxModel; obj.bound = &_sceneDynamicOpaqueObjectBounds[_numDynamicOpaqueObjects]; obj.prevWVP = &_prevWVPs[_numPrevWVPs]; obj.id = _highestSceneObjId++; genSceneObjectBounds(DYNAMIC_OBJ | OPAQUE_OBJ, _numDynamicOpaqueObjects, modelIndex); _numObjectBases++; _numPrevWVPs++; _numDynamicOpaqueObjects++; return &obj; }
UploadContext ResourceUploadBegin(uint64 size) { Assert_(Device != nullptr); size = AlignTo(size, 512); Assert_(size <= UploadBufferSize); Assert_(size > 0); ClearFinishedUploads(0); while(AllocUploadSubmission(size) == false) ClearFinishedUploads(1); Assert_(UploadSubmissionUsed > 0); const uint64 submissionIdx = (UploadSubmissionStart + (UploadSubmissionUsed - 1)) % MaxUploadSubmissions; UploadSubmission& submission = UploadSubmissions[submissionIdx]; Assert_(submission.Size == size); DXCall(submission.CmdAllocator->Reset()); DXCall(UploadCmdList->Reset(submission.CmdAllocator, nullptr)); UploadContext context; context.CmdList = UploadCmdList; context.Resource = UploadBuffer; context.CPUAddress = UploadBufferCPUAddr + submission.Offset; context.ResourceOffset = submission.Offset; return context; }
TempBuffer TempRawBuffer(uint64 numElements, bool makeDescriptor) { Assert_(numElements > 0); const uint64 stride = 4; MapResult tempMem = DX12::AcquireTempBufferMem(numElements * stride, stride); Assert_(tempMem.ResourceOffset % stride == 0); TempBuffer result; result.CPUAddress = tempMem.CPUAddress; if(makeDescriptor) { TempDescriptorAlloc srvAlloc = SRVDescriptorHeap.AllocateTemporary(1); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = { }; srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Buffer.FirstElement = uint32(tempMem.ResourceOffset / stride); srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; srvDesc.Buffer.NumElements = uint32(numElements); DX12::Device->CreateShaderResourceView(tempMem.Resource, &srvDesc, srvAlloc.StartCPUHandle); result.DescriptorIndex = srvAlloc.StartIndex; } return result; }
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); } }
void Profiler::StartProfile(const wstring& name) { ProfileData& profileData = profiles[name]; Assert_(profileData.QueryStarted == false); Assert_(profileData.QueryFinished == false); profileData.CPUProfile = false; profileData.Active = true; if(profileData.DisjointQuery[currFrame] == NULL) { // Create the queries D3D11_QUERY_DESC desc; desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; desc.MiscFlags = 0; DXCall(device->CreateQuery(&desc, &profileData.DisjointQuery[currFrame])); desc.Query = D3D11_QUERY_TIMESTAMP; DXCall(device->CreateQuery(&desc, &profileData.TimestampStartQuery[currFrame])); DXCall(device->CreateQuery(&desc, &profileData.TimestampEndQuery[currFrame])); } // Start a disjoint query first context->Begin(profileData.DisjointQuery[currFrame]); // Insert the start timestamp context->End(profileData.TimestampStartQuery[currFrame]); profileData.QueryStarted = true; }
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)); }
void PostProcessHelper::End() { Assert_(cmdList != nullptr); cmdList = nullptr; for(uint64 i = 0; i < tempRenderTargets.Count(); ++i) Assert_(tempRenderTargets[i]->InUse == false); }
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)); }
float InterpolateSpectrumSamples(const float *lambda, const float *vals, int n, float l) { for (int i = 0; i < n - 1; ++i) Assert_(lambda[i + 1] > lambda[i]); if (l <= lambda[0]) return vals[0]; if (l >= lambda[n - 1]) return vals[n - 1]; int offset = FindInterval(n, [&](int index) { return l >= lambda[index]; }); Assert_(l >= lambda[offset] && l <= lambda[offset + 1]); float t = (l - lambda[offset]) / (lambda[offset + 1] - lambda[offset]); return SpectrumLerp(t, vals[offset], vals[offset + 1]); }
void SettingsContainer::AddOrientationSetting(const char* name, const char* label, const char* group, Quaternion initialVal, const char* helpText) { Assert_(settings.find(name) == settings.end()); Assert_(tweakBar != nullptr); OrientationSetting* setting = new OrientationSetting(); setting->Initialize(tweakBar, name, group, label, helpText, initialVal); settings[name] = setting; allocatedSettings.push_back(setting); }
static bool AllocUploadSubmission(uint64 size) { Assert_(UploadSubmissionUsed <= MaxUploadSubmissions); if(UploadSubmissionUsed == MaxUploadSubmissions) return false; const uint64 submissionIdx = (UploadSubmissionStart + UploadSubmissionUsed) % MaxUploadSubmissions; Assert_(UploadSubmissions[submissionIdx].Size == 0); Assert_(UploadBufferUsed <= UploadBufferSize); if(size > (UploadBufferSize - UploadBufferUsed)) return false; const uint64 start = UploadBufferStart; const uint64 end = UploadBufferStart + UploadBufferUsed; uint64 allocOffset = uint64(-1); uint64 padding = 0; if(end < UploadBufferSize) { const uint64 endAmt = UploadBufferSize - end; if(endAmt >= size) { allocOffset = end; } else if(start >= size) { // Wrap around to the beginning allocOffset = 0; UploadBufferUsed += endAmt; padding = endAmt; } } else { const uint64 wrappedEnd = end % UploadBufferSize; if((start - wrappedEnd) >= size) allocOffset = wrappedEnd; } if(allocOffset == uint64(-1)) return false; UploadSubmissionUsed += 1; UploadBufferUsed += size; ++UploadFenceValue; UploadSubmissions[submissionIdx].Offset = allocOffset; UploadSubmissions[submissionIdx].Size = size; UploadSubmissions[submissionIdx].FenceValue = UploadFenceValue; UploadSubmissions[submissionIdx].Padding = padding; return true; }
void SettingsContainer::AddIntSetting(const char* name, const char* label, const char* group, int32 initialVal, int32 minVal, int32 maxVal, const char* helpText) { Assert_(settings.find(name) == settings.end()); Assert_(tweakBar != nullptr); IntSetting* setting = new IntSetting(); setting->Initialize(tweakBar, name, group, label, helpText, initialVal, minVal, maxVal); settings[name] = setting; allocatedSettings.push_back(setting); }
void SettingsContainer::AddEnumSetting(const char* name, const char* label, const char* group, uint32 initialVal, uint32 numValues, const char* const* valueLabels, const char* helpText) { Assert_(settings.find(name) == settings.end()); Assert_(tweakBar != nullptr); EnumSetting* setting = new EnumSetting(); setting->Initialize(tweakBar, name, group, label, helpText, initialVal, numValues, valueLabels); settings[name] = setting; allocatedSettings.push_back(setting); }
D3D12_GPU_DESCRIPTOR_HANDLE TempDescriptorTable(const D3D12_CPU_DESCRIPTOR_HANDLE* handles, uint64 count) { Assert_(count <= MaxBindCount); Assert_(count > 0); TempDescriptorAlloc tempAlloc = SRVDescriptorHeap.AllocateTemporary(uint32(count)); uint32 destRanges[1] = { uint32(count) }; Device->CopyDescriptors(1, &tempAlloc.StartCPUHandle, destRanges, uint32(count), handles, DescriptorCopyRanges, SRVDescriptorHeap.HeapType); return tempAlloc.StartGPUHandle; }
void Profiler::EndCPUProfile(const wstring& name) { ProfileData& profileData = profiles[name]; Assert_(profileData.QueryStarted == true); Assert_(profileData.QueryFinished == false); timer.Update(); profileData.EndTime = timer.ElapsedMicroseconds(); profileData.QueryStarted = false; profileData.QueryFinished = true; }
void SettingsContainer::AddFloatSetting(const char* name, const char* label, const char* group, float initialVal, float minVal, float maxVal, float step, const char* helpText) { Assert_(settings.find(name) == settings.end()); Assert_(tweakBar != nullptr); FloatSetting* setting = new FloatSetting(); setting->Initialize(tweakBar, name, group, label, helpText, initialVal, minVal, maxVal, step, ConversionMode::None, 1.0f); settings[name] = setting; allocatedSettings.push_back(setting); }
void SettingsContainer::AddColorSetting(const char* name, const char* label, const char* group, Float3 initialVal, bool hdr, float minIntensity, float maxIntensity, float step, const char* helpText) { Assert_(settings.find(name) == settings.end()); Assert_(tweakBar != nullptr); ColorSetting* setting = new ColorSetting(); setting->Initialize(tweakBar, name, group, label, helpText, initialVal, hdr, minIntensity, maxIntensity, step); settings[name] = setting; allocatedSettings.push_back(setting); }
void IntSetting::Initialize(TwBar* tweakBar_, const char* name_, const char* group_, const char* label_, const char* helpText_, int32 initialVal, int32 minVal_, int32 maxVal_) { val = initialVal; oldVal = initialVal; minVal = minVal_; maxVal = maxVal_; Assert_(minVal < maxVal); Assert_(minVal <= val && val <= maxVal); Setting::Initialize(tweakBar_, SettingType::Int, &val, name_, group_, label_, helpText_); TwHelper::SetMinMax(tweakBar, name.c_str(), minVal, maxVal); }
void FloatSetting::Initialize(TwBar* tweakBar_, const char* name_, const char* group_, const char* label_, const char* helpText_, float initialVal, float minVal_, float maxVal_, float step_) { val = initialVal; oldVal = initialVal; minVal = minVal_; maxVal = maxVal_; step = step_; Assert_(minVal < maxVal); Assert_(minVal <= val && val <= maxVal); Setting::Initialize(tweakBar_, SettingType::Float, &val, name_, group_, label_, helpText_); TwHelper::SetMinMax(tweakBar, name.c_str(), minVal, maxVal); TwHelper::SetStep(tweakBar, name.c_str(), step); }
void Profiler::EndProfile(const wstring& name) { ProfileData& profileData = profiles[name]; Assert_(profileData.QueryStarted == true); Assert_(profileData.QueryFinished == false); // Insert the end timestamp context->End(profileData.TimestampEndQuery[currFrame]); // End the disjoint query context->End(profileData.DisjointQuery[currFrame]); profileData.QueryStarted = false; profileData.QueryFinished = true; }
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // ¥ Test // ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ bool CBitArray::Test( TBitIndex inBit) { Assert_(inBit<mMax); return ((mBitArray[(inBit/32)] & (1 << (inBit%32))) !=0); }
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // ¥ Set // ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // Sets the bit specified void CBitArray::Set( TBitIndex inBit) { Assert_(inBit<mMax); mBitArray[(inBit/32)] |= 1 << (inBit%32); }
// ================================================================================================ // Problem 32 // ================================================================================================ sint32 Problem32() { CTable<uintn> products; // -- first handle single digit numbers // -- one can't work, because it would result in identical multiplier and product for(uintn i = 2; i <= 9; ++i) FindProducts(i, uintn(1) << i, products); // -- then double digit numbers for(uintn i = 1; i <= 9; ++i) { for(uintn j = 1; j <= 9; ++j) { if(i == j) continue; FindProducts(i*10 + j, uintn(1) << i | uintn(1) << j, products); } } // -- add all the products we collected in our table uintn result = 0; uintn count = products.Count(); for(uintn i = 0; i < count; ++i) result += products[i]; CLog::Write("The sum of the products is " UintNFmt_ "\n", result); Assert_(result == kAnswer, "The answer should have been " UintNFmt_, kAnswer); return 0; }
// ================================================================================================ // Problem 48 // ================================================================================================ int32 Problem48() { CBigInt result; result.SetDigitLimit(kNumDigits); CBigInt temp; temp.SetDigitLimit(kNumDigits); for(nuint i = 1; i <= kLastNumber; ++i) { // -- we don't need to bother with multiples of 10, since // -- they'll all end up with at least ten zeros in their least significant digits if((i % 10) == 0) continue; // -- initialize temp to 1 temp = 1; for(nuint j = 0; j < i; ++j) { temp *= i; } result += temp; } CLog::Write("The last " NUintFmt_ " digits of the sum are \"", kNumDigits); nflag correct = true; for(nuint i = kNumDigits; i > 0;) { --i; CLog::Write(NUintFmt_, result.Digit(i)); if(int8(result.Digit(i) + '0') != kAnswer[kNumDigits-i-1]) correct = false; } CLog::Write("\"\n"); Assert_(correct, "The answer should have been \"%s\"", kAnswer); return 0; }
void PostProcessor::DrawDepthBuffer(DepthStencilBuffer& depthBuffer, ID3D11RenderTargetView* rt) { Assert_(depthBuffer.SRView != nullptr); if(depthBuffer.MultiSamples > 1) PostProcess(depthBuffer.SRView, rt, drawDepthMSAA, L"Draw Depth"); else PostProcess(depthBuffer.SRView, rt, drawDepth, L"Draw Depth"); }
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // ¥ Clear // ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // Clears the bit specified void CBitArray::Clear( TBitIndex inBit) { Assert_(inBit<mMax); mBitArray[(inBit/32)] &= ~ (1 << (inBit%32)); }
template<typename T> void CompileShader(ID3D11Device* device, CompiledShader* shader) { Assert_(shader != nullptr); Assert_(*shader->Type == typeid(T)); vector<wstring> filePaths; D3D_SHADER_MACRO defines[CompileOptions::MaxDefines + 1]; shader->CompileOpts.MakeDefines(defines); shader->ByteCode = CompileShader(shader->FilePath.c_str(), shader->FunctionName.c_str(), shader->Profile.c_str(), defines, shader->ForceOptimization, filePaths); shader->ShaderPtr.Attach(CreateShader<T>(device, shader->ByteCode)); for(uint64 fileIdx = 0; fileIdx < filePaths.size(); ++ fileIdx) { const wstring& filePath = filePaths[fileIdx]; ShaderFile* shaderFile = nullptr; for(uint64 shaderFileIdx = 0; shaderFileIdx < ShaderFiles.size(); ++shaderFileIdx) { if(ShaderFiles[shaderFileIdx]->FilePath == filePath) { shaderFile = ShaderFiles[shaderFileIdx]; break; } } if(shaderFile == nullptr) { shaderFile = new ShaderFile(filePath); ShaderFiles.push_back(shaderFile); } bool containsShader = false; for(uint64 shaderIdx = 0; shaderIdx < shaderFile->Shaders.size(); ++shaderIdx) { if(shaderFile->Shaders[shaderIdx] == shader) { containsShader = true; break; } } if(containsShader == false) shaderFile->Shaders.push_back(shader); } }