[D3D12] Constant buffer binding
This commit is contained in:
@@ -68,8 +68,8 @@ void UploadBufferPool::ClearCache() {
|
||||
uint8_t* UploadBufferPool::RequestFull(uint32_t size,
|
||||
ID3D12Resource*& buffer_out,
|
||||
uint32_t& offset_out) {
|
||||
assert_true(size != 0 && size <= page_size_);
|
||||
if (size == 0 || size > page_size_) {
|
||||
assert_true(size <= page_size_);
|
||||
if (size > page_size_) {
|
||||
return nullptr;
|
||||
}
|
||||
if (page_size_ - current_size_ < size || current_mapping_ == nullptr) {
|
||||
@@ -89,10 +89,6 @@ uint8_t* UploadBufferPool::RequestPartial(uint32_t size,
|
||||
ID3D12Resource*& buffer_out,
|
||||
uint32_t& offset_out,
|
||||
uint32_t& size_out) {
|
||||
assert_true(size != 0);
|
||||
if (size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
if (current_size_ == page_size_ || current_mapping_ == nullptr) {
|
||||
// Start a new page if can't fit any bytes or don't have an open page.
|
||||
if (!BeginNextPage()) {
|
||||
@@ -216,7 +212,7 @@ void DescriptorHeapPool::BeginFrame() {
|
||||
void DescriptorHeapPool::EndFrame() { EndPage(); }
|
||||
|
||||
void DescriptorHeapPool::ClearCache() {
|
||||
assert(current_size_ == 0);
|
||||
assert_true(current_size_ == 0);
|
||||
while (unsent_ != nullptr) {
|
||||
auto next = unsent_->next;
|
||||
unsent_->heap->Release();
|
||||
@@ -232,36 +228,39 @@ void DescriptorHeapPool::ClearCache() {
|
||||
sent_last_ = nullptr;
|
||||
}
|
||||
|
||||
uint64_t DescriptorHeapPool::GetPageForRequest(uint32_t count) const {
|
||||
uint64_t page = current_page_;
|
||||
if (page_size_ - current_size_ < count) {
|
||||
++page;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
bool DescriptorHeapPool::Request(uint32_t count, uint32_t& index_out) {
|
||||
assert_true(count != 0 && count <= page_size_);
|
||||
if (count == 0 || count > page_size_) {
|
||||
return false;
|
||||
uint64_t DescriptorHeapPool::Request(uint64_t previous_full_update,
|
||||
uint32_t count_for_partial_update,
|
||||
uint32_t count_for_full_update,
|
||||
uint32_t& index_out) {
|
||||
assert_true(count_for_partial_update <= count_for_full_update);
|
||||
assert_true(count_for_full_update <= page_size_);
|
||||
if (count_for_partial_update > count_for_full_update ||
|
||||
count_for_full_update > page_size_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (page_creation_failed_) {
|
||||
// Don't increment the page index every call if there was a failure as well.
|
||||
return false;
|
||||
// Don't touch the page index every call if there was a failure as well.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Go to the next page if there's not enough free space on the current one.
|
||||
// If the last full update happened on the current page, a partial update is
|
||||
// possible.
|
||||
uint32_t count = previous_full_update == current_page_
|
||||
? count_for_partial_update
|
||||
: count_for_full_update;
|
||||
|
||||
// Go to the next page if there's not enough free space on the current one,
|
||||
// or because the previous page may be outdated. In this case, a full update
|
||||
// is necessary.
|
||||
if (page_size_ - current_size_ < count) {
|
||||
EndPage();
|
||||
++current_page_;
|
||||
count = count_for_full_update;
|
||||
}
|
||||
|
||||
// Create the page if needed (may be the first call for the page).
|
||||
if (unsent_ == nullptr) {
|
||||
if (page_creation_failed_) {
|
||||
return false;
|
||||
}
|
||||
auto device = context_->GetD3D12Provider()->GetDevice();
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heap_desc;
|
||||
heap_desc.Type = type_;
|
||||
@@ -273,7 +272,7 @@ bool DescriptorHeapPool::Request(uint32_t count, uint32_t& index_out) {
|
||||
XELOGE("Failed to create a heap for %u shader-visible descriptors",
|
||||
page_size_);
|
||||
page_creation_failed_ = true;
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
unsent_ = new DescriptorHeap;
|
||||
unsent_->heap = heap;
|
||||
@@ -289,7 +288,7 @@ bool DescriptorHeapPool::Request(uint32_t count, uint32_t& index_out) {
|
||||
}
|
||||
index_out = current_size_;
|
||||
current_size_ += count;
|
||||
return true;
|
||||
return current_page_;
|
||||
}
|
||||
|
||||
void DescriptorHeapPool::EndPage() {
|
||||
|
||||
@@ -71,13 +71,34 @@ class DescriptorHeapPool {
|
||||
void EndFrame();
|
||||
void ClearCache();
|
||||
|
||||
// To check if a rebind will be required, and thus may possibly need to write
|
||||
// all the descriptors needed for a draw call rather than only the modified
|
||||
// ones. The page number can never be 0 if a frame has started, and it's
|
||||
// changed every frame, so it's safe to use 0 to indicate that the descriptors
|
||||
// for some data have never been written.
|
||||
uint64_t GetPageForRequest(uint32_t count) const;
|
||||
bool Request(uint32_t count, uint32_t& index_out);
|
||||
// Because all descriptors for a single draw call must be in the same heap,
|
||||
// sometimes all descriptors, rather than only the modified portion of it,
|
||||
// needs to be written.
|
||||
//
|
||||
// This may happen if there's not enough free space even for a partial update
|
||||
// in the current heap, or if the heap which contains the unchanged part of
|
||||
// the descriptors is outdated.
|
||||
//
|
||||
// If something uses this pool to do partial updates, it must let this
|
||||
// function determine whether a partial update is possible. For this purpose,
|
||||
// this function returns a full update number - and it must be called with its
|
||||
// previous return value for the set of descriptors it's updating.
|
||||
//
|
||||
// If this function returns a value that is the same as previous_full_update,
|
||||
// a partial update needs to be done - and space for count_for_partial_update
|
||||
// is allocated.
|
||||
//
|
||||
// If it's different, all descriptors must be written again - and space for
|
||||
// count_for_full_update is allocated.
|
||||
//
|
||||
// If 0 is returned, there was an error.
|
||||
//
|
||||
// This MUST be called even if there's nothing to write in a partial update
|
||||
// (with count_for_partial_update being 0), because a full update may still be
|
||||
// required.
|
||||
uint64_t Request(uint64_t previous_full_update,
|
||||
uint32_t count_for_partial_update,
|
||||
uint32_t count_for_full_update, uint32_t& index_out);
|
||||
|
||||
// The current heap, for binding and actually writing - may be called only
|
||||
// after a successful request because before a request, the heap may not exist
|
||||
@@ -89,7 +110,6 @@ class DescriptorHeapPool {
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetLastRequestHeapGPUStart() const {
|
||||
return current_heap_gpu_start_;
|
||||
}
|
||||
uint64_t GetLastRequestPageNumber() const { return current_page_; }
|
||||
|
||||
private:
|
||||
D3D12Context* context_;
|
||||
|
||||
Reference in New Issue
Block a user