void GuiRendererD3D11::Leave(NFE_CONTEXT_ARG) { auto pCtx = (RenderContextD3D11*)pContext; auto pRenderer = pCtx->GetRenderer(); FlushQueue(pCtx); pCtx->ResetShader(ShaderType::Geometry); pCtx->D3DContext->OMSetBlendState(pRenderer->defaultBlendState, 0, 0xFFFFFFFF); }
void RenderToVolumeTexture(const Ptr<Texture> & volumeTexture) { auto rc = Global::GetRenderEngine()->GetRenderContext(); auto & quadVBs = GetQuadVBs(); auto & quadIB = GetQuadIB(); RenderViewport vp; vp.topLeftX = 0.0f; vp.topLeftY = 0.0f; vp.width = static_cast<float>(volumeTexture->GetDesc().width); vp.height = static_cast<float>(volumeTexture->GetDesc().height); vp.minDepth = 0.0f; vp.maxDepth = 1.0f; rc->SetViewport(vp); float2 uvMap[4]; uvMap[0] = float2(0.0f, 0.0f); uvMap[1] = float2(1.0f, 0.0f); uvMap[2] = float2(0.0f, 1.0f); uvMap[3] = float2(1.0f, 1.0f); auto uvBufMappedData = quadVBs[1]->Map(MAP_WRITE_DISCARD); memcpy(uvBufMappedData.pData, uvMap, sizeof(float2) * 4); quadVBs[1]->UnMap(); // Set vbs, ib rc->SetVertexBuffer(quadVBs); rc->SetIndexBuffer(quadIB); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Set rtv rc->SetRenderTargets({ volumeTexture->GetRenderTargetView(0, 0, volumeTexture->GetDesc().depth) }); // Set dsv rc->SetDepthStencilState(DepthStencilStateTemplate<false>::Get()); // Bind shader auto vs = Shader::FindOrCreate<RenderToVolumeTextureVS>(); auto gs = Shader::FindOrCreate<RenderToVolumeTextureGS>(); vs->Flush(); gs->Flush(); // Draw rc->DrawIndexedInstanced(quadIB->GetDesc().numElements, volumeTexture->GetDesc().depth, 0, 0, 0); rc->SetDepthStencilState(nullptr); rc->ResetShader(SHADER_GS); }
void FFT::FFT2DRadix8( const Ptr<Texture> & src, int32_t srcMipLevel, int32_t srcArrayOffset, const Ptr<Texture> & dst, int32_t dstMipLevel, int32_t dstArrayOffset, bool bInverse, bool bIFFTScale) { auto mipSize = src->GetMipSize(srcMipLevel); TextureDesc texDesc; texDesc.width = mipSize.x(); texDesc.height = mipSize.y(); texDesc.depth = 1; texDesc.bindFlag = TEXTURE_BIND_SHADER_RESOURCE | TEXTURE_BIND_RENDER_TARGET | TEXTURE_BIND_UNORDERED_ACCESS; texDesc.cpuAccess = 0; texDesc.format = RENDER_FORMAT_R32G32_FLOAT; texDesc.mipLevels = 1; texDesc.arraySize = 1; texDesc.bCube = false; texDesc.sampleCount = 1; texDesc.sampleQuality = 0; PooledTextureRef bfSrcRef; Ptr<Texture> bfSrc; int32_t bfSrcMipLevel = 0; int32_t bfSrcArrayOffset = 0; //if (!bInverse) //{ // bfSrcRef = TexturePool::Instance().FindFree({ TEXTURE_2D, texDesc }); // bfSrc = bfSrcRef->Get()->Cast<Texture>(); // FFT::FFTSetup(src, srcMipLevel, srcArrayOffset, bfSrc, 0, 0); //} //else { bfSrc = src; bfSrcMipLevel = srcMipLevel; bfSrcArrayOffset = srcArrayOffset; } PooledTextureRef bfDstRef; Ptr<Texture> bfDst; int32_t bfDstMipLevel = 0; int32_t bfDstArrayOffset = 0; if (dst->GetDesc().bindFlag & TEXTURE_BIND_UNORDERED_ACCESS && dst->GetDesc().format == RENDER_FORMAT_R32G32_FLOAT) { bfDst = dst; bfDstMipLevel = dstMipLevel; bfDstArrayOffset = dstArrayOffset; } else { bfDstRef = TexturePool::Instance().FindFree({ TEXTURE_2D, texDesc }); bfDst = bfDstRef->Get()->Cast<Texture>(); } std::map<String, String> macros; macros["FFT_2D"] = ""; if (bInverse) { macros["FFT_INVERSE"] = ""; if(bIFFTScale) macros["FFT_INVERSE_SCALE"] = ""; } static int fftGroupSize = 64; macros["FFT_GROUP_SIZE"] = std::to_string(fftGroupSize); auto fftXCS = Shader::FindOrCreate<FFTRadix8_2D_XCS>(macros); auto fftXFinalCS = Shader::FindOrCreate<FFTRadix8_2D_X_FinalCS>(macros); auto fftYCS = Shader::FindOrCreate<FFTRadix8_2D_YCS>(macros); auto fftYFinalCS = Shader::FindOrCreate<FFTRadix8_2D_Y_FinalCS>(macros); auto ifftScalePS = Shader::FindOrCreate<IFFTScalePS>(); float4 dataSize = float4((float)mipSize.x(), (float)mipSize.y(), 1.0f / (float)mipSize.x(), 1.0f / (float)mipSize.y()); auto rc = Global::GetRenderEngine()->GetRenderContext(); //FFT X { uint32_t numGroups = texDesc.width / fftGroupSize / 8; uint32_t threadCount = texDesc.width / 8; uint32_t ostride = threadCount; uint32_t istride = threadCount; float phaseBase = -PI2 / texDesc.width; if (bInverse) phaseBase *= -1.0f; while (istride > 0) { if (istride > 1) { fftXCS->SetScalar("dataSize", dataSize); fftXCS->SetScalar("threadCount", threadCount); fftXCS->SetScalar("ostride", ostride); fftXCS->SetScalar("istride", istride); fftXCS->SetScalar("phaseBase", phaseBase); fftXCS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); fftXCS->SetUAV("dstTex", bfDst->GetUnorderedAccessView(bfDstMipLevel, bfDstArrayOffset, 1)); fftXCS->Flush(); rc->Compute(numGroups, texDesc.height, 1); } else { fftXFinalCS->SetScalar("dataSize", dataSize); fftXFinalCS->SetScalar("threadCount", threadCount); fftXFinalCS->SetScalar("ostride", ostride); fftXFinalCS->SetScalar("istride", istride); fftXFinalCS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); fftXFinalCS->SetUAV("dstTex", bfDst->GetUnorderedAccessView(bfDstMipLevel, bfDstArrayOffset, 1)); fftXFinalCS->Flush(); rc->Compute(numGroups, texDesc.height, 1); } std::swap(bfSrc, bfDst); std::swap(bfSrcMipLevel, bfDstMipLevel); std::swap(bfSrcArrayOffset, bfDstArrayOffset); istride /= 8; phaseBase *= 8.0f; } } //FFT Y { uint32_t numGroups = texDesc.height / fftGroupSize / 8; uint32_t threadCount = texDesc.height / 8; uint32_t ostride = threadCount; uint32_t istride = threadCount; float phaseBase = -PI2 / texDesc.height; if (bInverse) phaseBase *= -1.0f; while (istride > 0) { if (istride > 1) { fftYCS->SetScalar("dataSize", dataSize); fftYCS->SetScalar("threadCount", threadCount); fftYCS->SetScalar("ostride", ostride); fftYCS->SetScalar("istride", istride); fftYCS->SetScalar("phaseBase", phaseBase); fftYCS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); fftYCS->SetUAV("dstTex", bfDst->GetUnorderedAccessView(bfDstMipLevel, bfDstArrayOffset, 1)); fftYCS->Flush(); rc->Compute(numGroups, texDesc.width, 1); } else { fftYFinalCS->SetScalar("dataSize", dataSize); fftYFinalCS->SetScalar("threadCount", threadCount); fftYFinalCS->SetScalar("ostride", ostride); fftYFinalCS->SetScalar("istride", istride); fftYFinalCS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); fftYFinalCS->SetUAV("dstTex", bfDst->GetUnorderedAccessView(bfDstMipLevel, bfDstArrayOffset, 1)); fftYFinalCS->Flush(); rc->Compute(numGroups, texDesc.width, 1); } std::swap(bfSrc, bfDst); std::swap(bfSrcMipLevel, bfDstMipLevel); std::swap(bfSrcArrayOffset, bfDstArrayOffset); istride /= 8; phaseBase *= 8.0f; } } rc->ResetShader(SHADER_CS); //Clear if (bfSrc != dst) //dst is result { bfSrc->CopyTo(dst, dstMipLevel, dstArrayOffset, 0, 0, 0, 0, 0); } }
void FFT::FFT2DRadix2( const Ptr<Texture> & src, int32_t srcMipLevel, int32_t srcArrayOffset, const Ptr<Texture> & dst, int32_t dstMipLevel, int32_t dstArrayOffset, bool bInverse, bool bIFFTScale) { auto mipSize = src->GetMipSize(srcMipLevel); TextureDesc texDesc; texDesc.width = mipSize.x(); texDesc.height = mipSize.y(); texDesc.depth = 1; texDesc.bindFlag = TEXTURE_BIND_SHADER_RESOURCE | TEXTURE_BIND_RENDER_TARGET | TEXTURE_BIND_UNORDERED_ACCESS; texDesc.cpuAccess = 0; texDesc.format = RENDER_FORMAT_R32G32_FLOAT; texDesc.mipLevels = 1; texDesc.arraySize = 1; texDesc.bCube = false; texDesc.sampleCount = 1; texDesc.sampleQuality = 0; PooledTextureRef bfSrcRef; Ptr<Texture> bfSrc; int32_t bfSrcMipLevel = 0; int32_t bfSrcArrayOffset = 0; /*if (!bInverse) { bfSrcRef = TexturePool::Instance().FindFree({ TEXTURE_2D, texDesc }); bfSrc = bfSrcRef->Get()->Cast<Texture>(); FFT::FFTSetup(src, srcMipLevel, srcArrayOffset, bfSrc, 0, 0); } else*/ { bfSrc = src; bfSrcMipLevel = srcMipLevel; bfSrcArrayOffset = srcArrayOffset; } PooledTextureRef bfDstRef; Ptr<Texture> bfDst; int32_t bfDstMipLevel = 0; int32_t bfDstArrayOffset = 0; if (dst->GetDesc().bindFlag & TEXTURE_BIND_UNORDERED_ACCESS && dst->GetDesc().format == RENDER_FORMAT_R32G32_FLOAT) { bfDst = dst; bfDstMipLevel = dstMipLevel; bfDstArrayOffset = dstArrayOffset; } else { bfDstRef = TexturePool::Instance().FindFree({ TEXTURE_2D, texDesc }); bfDst = bfDstRef->Get()->Cast<Texture>(); } std::map<String, String> macros; macros["FFT_2D"] = ""; if (bInverse) { macros["FFT_INVERSE"] = ""; if (bIFFTScale) macros["FFT_INVERSE_SCALE"] = ""; } static int fftGroupSize = 64; macros["FFT_GROUP_SIZE"] = std::to_string(fftGroupSize); auto fftXCS = Shader::FindOrCreate<FFTRadix2_2D_XCS>(macros); auto fftYCS = Shader::FindOrCreate<FFTRadix2_2D_YCS>(macros); auto ifftScalePS = Shader::FindOrCreate<IFFTScalePS>(); float4 dataSize = float4((float)mipSize.x(), (float)mipSize.y(), 1.0f / (float)mipSize.x(), 1.0f / (float)mipSize.y()); auto rc = Global::GetRenderEngine()->GetRenderContext(); //Butterfly X { uint32_t numGroups = std::max<uint32_t>(1, texDesc.width / fftGroupSize / 2); uint32_t bfLen = 2; while (bfLen <= static_cast<uint32_t>(texDesc.width)) { fftXCS->SetScalar("dataSize", dataSize); fftXCS->SetScalar("butterflyLength", bfLen); fftXCS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); fftXCS->SetUAV("dstTex", bfDst->GetUnorderedAccessView(bfDstMipLevel, bfDstArrayOffset, 1)); fftXCS->Flush(); rc->Compute(numGroups, texDesc.height, 1); std::swap(bfSrc, bfDst); std::swap(bfSrcMipLevel, bfDstMipLevel); std::swap(bfSrcArrayOffset, bfDstArrayOffset); bfLen = bfLen << 1; } rc->ResetShader(SHADER_CS); if (bInverse && bIFFTScale) { float ifftScale = 1.0f / (float)texDesc.width; ifftScalePS->SetScalar("ifftScale", ifftScale); ifftScalePS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); ifftScalePS->SetSampler("pointSampler", SamplerTemplate<FILTER_MIN_MAG_MIP_POINT>::Get()); ifftScalePS->Flush(); DrawQuad({ bfDst->GetRenderTargetView(dstMipLevel, dstArrayOffset, 1) }); std::swap(bfSrc, bfDst); std::swap(bfSrcMipLevel, bfDstMipLevel); std::swap(bfSrcArrayOffset, bfDstArrayOffset); } } //Butterfly Y { uint32_t numGroups = std::max<uint32_t>(1, texDesc.height / fftGroupSize / 2); uint32_t bfLen = 2; while (bfLen <= static_cast<uint32_t>(texDesc.height)) { fftYCS->SetScalar("dataSize", dataSize); fftYCS->SetScalar("butterflyLength", bfLen); fftYCS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); fftYCS->SetUAV("dstTex", bfDst->GetUnorderedAccessView(bfDstMipLevel, bfDstArrayOffset, 1)); fftYCS->Flush(); rc->Compute(numGroups, texDesc.width, 1); std::swap(bfSrc, bfDst); std::swap(bfSrcMipLevel, bfDstMipLevel); std::swap(bfSrcArrayOffset, bfDstArrayOffset); bfLen = bfLen << 1; } rc->ResetShader(SHADER_CS); if (bInverse && bIFFTScale) { float ifftScale = 1.0f / texDesc.height; ifftScalePS->SetScalar("ifftScale", ifftScale); ifftScalePS->SetSRV("srcTex", bfSrc->GetShaderResourceView(bfSrcMipLevel, 1, bfSrcArrayOffset, 1)); ifftScalePS->SetSampler("pointSampler", SamplerTemplate<FILTER_MIN_MAG_MIP_POINT>::Get()); ifftScalePS->Flush(); DrawQuad({ bfDst->GetRenderTargetView(dstMipLevel, dstArrayOffset, 1) }); std::swap(bfSrc, bfDst); std::swap(bfSrcMipLevel, bfDstMipLevel); std::swap(bfSrcArrayOffset, bfDstArrayOffset); } } //Clear if (bfSrc != dst) //dst is result { bfSrc->CopyTo(dst, dstMipLevel, dstArrayOffset, 0, 0, 0, 0, 0); } }
/***************************************************************************** Name: PVRUniPatchFinaliseShader Purpose: Generates a HW-executable shader from a patchable USP shader. Inputs: pvContext - The current USP execution context pvShader - The runtime-patcheable shader for which HW code should be generated Outputs: none Returns: Pointer to a structure containing the HW instructions and associated meta-data needed by a driver. *****************************************************************************/ EXPORT_FOR_TEST_ONLY PUSP_HW_SHADER IMG_CALLCONV PVRUniPatchFinaliseShader( IMG_PVOID pvContext, IMG_PVOID pvShader) { PUSP_CONTEXT psContext; PUSP_SHADER psShader; PUSP_HW_SHADER psHWShader; IMG_UINT32 uSmpIdx; psContext = (PUSP_CONTEXT)pvContext; psShader = (PUSP_SHADER)pvShader; psHWShader = IMG_NULL; /* Initialize all texture control words as not set */ for(uSmpIdx=0; uSmpIdx<psShader->uTotalSmpTexCtrWrds; uSmpIdx++) { IMG_UINT32 uPlnIdx; psShader->psTexCtrWrds[uSmpIdx].bUsed = IMG_FALSE; for (uPlnIdx=0; uPlnIdx<USP_TEXFORM_MAX_PLANE_COUNT; uPlnIdx++) { psShader->psTexCtrWrds[uSmpIdx].auWords[uPlnIdx] = (IMG_UINT32)-1; psShader->psTexCtrWrds[uSmpIdx].auTexWrdIdx[uPlnIdx] = (IMG_UINT16)-1; psShader->psTexCtrWrds[uSmpIdx].abExtFmt[uPlnIdx] = IMG_FALSE; psShader->psTexCtrWrds[uSmpIdx].abReplicate[uPlnIdx] = IMG_FALSE; psShader->psTexCtrWrds[uSmpIdx].aeUnPackFmts[uPlnIdx] = USP_REGFMT_UNKNOWN; psShader->psTexCtrWrds[uSmpIdx].auSwizzle[uPlnIdx] = (IMG_UINT32)-1; psShader->psTexCtrWrds[uSmpIdx].abMinPack[uPlnIdx] = IMG_FALSE; psShader->psTexCtrWrds[uSmpIdx].auTagSize[uPlnIdx] = 0; } } /* Add texture formats to USP sample blocks */ if (!HandleUSPSampleTextureFormat(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error adding sample data to shader for finalisation\n")); return IMG_NULL; } /* Insert preamble code as required */ if (!FinaliseShaderPreamble(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising shader preamble code\n")); return IMG_NULL; } /* Finalise the location of results and temporary data used for samples */ if (!FinaliseResultLocations(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising result locations\n")); return IMG_NULL; } /* Generate code for samples */ if (!FinaliseSamples(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising texture-samples\n")); return IMG_NULL; } /* Generate code for texture writes */ if (!FinaliseTextureWriteList(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising texture write list\n")); return IMG_NULL; } /* Finalise the overall register counts now that we know how many are required by samples */ if (!FinaliseRegCounts(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising temp/pa counts\n")); return IMG_NULL; } /* Finalise the shader results */ if (!FinaliseResults(psContext, psShader)) { USP_DBGPRINT(("PVRUniPatchFinaliseShader: Error finalising results\n")); return IMG_NULL; } /* Finalise the instructions within all blocks */ if (!FinaliseInstructions(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising instructions\n")); return IMG_NULL; } /* Fixup branch destinations now that we have generated all instructions */ if (!FinaliseBranches(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error finalising branch destinations\n")); return IMG_NULL; } /* Remove excess trailing iterations that may have been added by the USC to stop the USP overwriting shader results when in PA registers */ if (!RemoveDummyIterations(psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error removing excess PS input data\n" )); return IMG_NULL; } /* Generate the HW structure encapsulating the finalised shader code */ psHWShader = CreateHWShader(psContext, psShader); if (!psHWShader) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Failed to create HW shader\n")); return IMG_NULL; } /* Reset any data that is altered during finalisation */ if (!ResetShader(psContext, psShader)) { USP_DBGPRINT(( "PVRUniPatchFinaliseShader: Error resetting shader for finalisation\n")); psContext->pfnFree(psHWShader); return IMG_NULL; } return psHWShader; }
void ImageBasedLensFlare::LensBlur(const Ptr<Texture> & setupTex, const Ptr<Texture> & target) { int32_t tileSize = 9; //Extract Sprite Points int32_t extractWidth = (setupTex->GetDesc().width + tileSize - 1) / tileSize; int32_t extractHeight = (setupTex->GetDesc().height + tileSize - 1) / tileSize; RenderBufferDesc spPointsBufDesc; spPointsBufDesc.bindFlag = BUFFER_BIND_SHADER_RESOURCE | BUFFER_BIND_UNORDERED_ACCESS; spPointsBufDesc.elementSize = sizeof(float2) + sizeof(float3); spPointsBufDesc.numElements = extractWidth * extractHeight; spPointsBufDesc.cpuAccess = 0; spPointsBufDesc.bStructured = true; auto spPointsBufRef = BufferPool::Instance().FindFree(spPointsBufDesc); auto spPointsBuf = spPointsBufRef->Get()->Cast<RenderBuffer>(); { auto ps = Shader::FindOrCreate<ExtractSpritePointsPS>(); ps->SetScalar("spriteThreshold", _spriteThreshold); ps->SetSRV("setupTex", setupTex->GetShaderResourceView()); ps->SetUAV("spPointsBuf", spPointsBuf->GetUnorderedAccessView(0, 0, RENDER_FORMAT_UNKNOWN, BUFFER_UAV_APPEND)); ps->Flush(); DrawQuad({}, 0.0f, 0.0f, (float)extractWidth, (float)extractHeight); } //Render Sprites if (!_indirectAgsBuf) { RenderBufferDesc indirectArgsBufDesc; indirectArgsBufDesc.bindFlag = BUFFER_BIND_INDIRECT_ARGS; indirectArgsBufDesc.elementSize = 16; indirectArgsBufDesc.numElements = 1; indirectArgsBufDesc.cpuAccess = 0; indirectArgsBufDesc.bStructured = false; uint32_t initData[] = { 0, 1, 0, 0 }; _indirectAgsBuf = Global::GetRenderEngine()->GetRenderFactory()->CreateBuffer(); _indirectAgsBuf->SetDesc(indirectArgsBufDesc); _indirectAgsBuf->Init(initData); } spPointsBuf->CopyStructureCountTo(_indirectAgsBuf, 0, 0, spPointsBuf->GetDesc().numElements, RENDER_FORMAT_UNKNOWN, BUFFER_UAV_APPEND); { auto vs = Shader::FindOrCreate<LensBlurVS>(); auto gs = Shader::FindOrCreate<LensBlurGS>(); auto ps = Shader::FindOrCreate<LensBlurPS>(); vs->SetScalar("texSize", target->GetTexSize()); gs->SetScalar("texSize", target->GetTexSize()); gs->SetScalar("flareIntensity", _flareIntensity); vs->SetSRV("spPointsRenderBuf", spPointsBuf->GetShaderResourceView(0, 0, RENDER_FORMAT_UNKNOWN)); auto lensTexAsset = Asset::Find<TextureAsset>("Textures/Bokeh_Circle.dds"); if (!lensTexAsset->IsInit()) lensTexAsset->Init(); auto lensTex = lensTexAsset->GetTexture(); ps->SetSRV("lensTex", lensTex->GetShaderResourceView()); ps->SetSampler("linearSampler", SamplerTemplate<>::Get()); vs->Flush(); gs->Flush(); ps->Flush(); auto rc = Global::GetRenderEngine()->GetRenderContext(); rc->SetVertexBuffer({}); rc->SetIndexBuffer(nullptr); rc->SetPrimitiveTopology(PRIMITIVE_TOPOLOGY_POINTLIST); rc->SetViewport(GetTextureQuadViewport(target)); rc->SetRenderTargets({ target->GetRenderTargetView(0, 0, 1) }); rc->SetDepthStencil(nullptr); rc->SetDepthStencilState(DepthStencilStateTemplate<false>::Get()); rc->SetBlendState(BlendStateTemplate<false, false, true, BLEND_PARAM_SRC_ALPHA, BLEND_PARAM_ONE, BLEND_OP_ADD>::Get()); rc->DrawInstancedIndirect(_indirectAgsBuf, 0); rc->ResetShader(SHADER_GS); rc->SetBlendState(nullptr); } }